using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using Terra.Core.Infrastructure.Security;
using Terra.Core.Security;
using Terra.Service.Identity.Interfaces;
using Terra.Service.Identity.Implementations;
using Terra.Service.Logging.Interfaces;
using Terra.Service.Logging.Implementations;
using Terra.Data.Repository.Logging;
using Microsoft.Extensions.Configuration;
using Terra.Core.Infrastructure.Email.Interfaces;
using Terra.Core.Infrastructure.Email.Services;
using Terra.Core.Infrastructure.SMS.Interfaces;
using Terra.Core.Infrastructure.SMS.Services;
using Terra.Data.Repository.Identity;
using Terra.Service.Identity.Interfaces;

namespace Terra.Service.Common.Extensions;

/// <summary>
/// IServiceCollection的扩展方法
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 注册所有应用服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddApplicationServices(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        #region 基础设施服务
        // 用户上下文
        services.AddScoped<ICurrentUser, CurrentUser>();

        // 邮件服务
        services.AddEmailService(configuration);

        // 短信服务
        services.AddSmsService(configuration);
        #endregion

        #region 认证授权服务
        // 身份认证服务
        services.AddScoped<IAuthService, AuthService>();
        services.AddScoped<IUserService, UserService>();
        // 角色服务
        services.AddScoped<IRoleService, RoleService>();
        // 菜单服务
        services.AddScoped<IMenuService, MenuService>();
        // 部门服务
        services.AddScoped<IDeptService, DeptService>();
        // 权限服务
        services.AddScoped<IPermissionService, PermissionService>();

        #endregion

        #region 数据访问服务
        // 认证相关仓储
        services.AddIdentityRepositories();

        // 日志仓储
        services.AddScoped<ILoginLogRepository, LoginLogRepository>();
        services.AddScoped<IExceptionLogRepository, ExceptionLogRepository>();
        #endregion

        #region 业务服务
        // 日志服务
        services.AddScoped<ILoginLogService, LoginLogService>();
        services.AddScoped<IExceptionLogService, ExceptionLogService>();
        #endregion

        #region 对象映射
        // 注册AutoMapper
        var assemblies = new[]
        {
            Assembly.Load("Terra.Service"),
            Assembly.Load("Terra.Data")
        };
        services.AddAutoMapper(assemblies);
        #endregion

        return services;
    }

    /// <summary>
    /// 添加身份认证相关仓储
    /// </summary>
    private static IServiceCollection AddIdentityRepositories(this IServiceCollection services)
    {
        // 用户仓储
        services.AddScoped<IUserRepository, UserRepository>();

        // 角色仓储
        services.AddScoped<IRoleRepository, RoleRepository>();

        // 刷新令牌仓储
        services.AddScoped<IRefreshTokenRepository, RefreshTokenRepository>();

        // 密码重置令牌仓储
        services.AddScoped<IPasswordResetTokenRepository, PasswordResetTokenRepository>();

        // 部门仓储
        services.AddScoped<IDeptRepository, DeptRepository>();

        // 权限仓储
        services.AddScoped<IPermissionRepository, PermissionRepository>();

        return services;
    }

    #region 基础设施服务注册

    /// <summary>
    /// 添加邮件服务
    /// </summary>
    private static IServiceCollection AddEmailService(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        services.Configure<Terra.Core.Infrastructure.Email.Options.EmailOptions>(
            configuration.GetSection("Email")
        );
        services.AddScoped<IEmailSender, SmtpEmailSender>();
        return services;
    }

    /// <summary>
    /// 添加短信服务
    /// </summary>
    private static IServiceCollection AddSmsService(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        services.Configure<Terra.Core.Infrastructure.SMS.Options.SmsOptions>(
            configuration.GetSection("Sms")
        );
        services.AddHttpClient<ISmsSender, DefaultSmsSender>();
        return services;
    }

    #endregion
}